1651. Multiplication Puzzle

 

The multiplication puzzle is played with a row of cards, each containing a single positive integer. During the move player takes one card out of the row and scores the number of points equal to the product of the number on the card taken and the numbers on the cards on the left and on the right of it. It is not allowed to take out the first and the last card in the row. After the final move, only two cards are left in the row.

The goal is to take cards in such order as to minimize the total number of scored points.

For example, if cards in the row contain numbers 10 1 50 20 5, player might take a card with 1, then 20 and 50, scoring

10*1*50 + 50*20*5 + 10*50*5 = 500 + 5000 + 2500 = 8000

If he would take the cards in the opposite order, i.e. 50, then 20, then 1, the score would be

1*50*20 + 1*20*5 + 10*1*5 = 1000 + 100 + 50 = 1150

 

Input. The first line contains the number of cards n (3 ≤ n ≤ 100). The second line contains n integers in the range from 1 to 100, separated by spaces.

 

Output. Output must contain a single integer – the minimal score.

 

Пример входа

Пример выхода

6

10 1 50 50 20 5

3650

 

 

РЕШЕНИЕ

динамическое программирование

 

Анализ алгоритма

Входную последовательность карт занесем в массив a[0, …, n – 1]. Пусть f(i, j) – наименьшее количество баллов, которое можно получить, удалив все карты строго внутри отрезка [ai, …, aj] (кроме крайних двух ai и aj, крайние карты по условию задачи удалять нельзя). Сохраним это значение в ячейке dp[i][j]. Тогда ответом на задачу будет f(0, n – 1).

Занесем в ячейки массива dp значения INF = ∞, инициализируем dp[i][i] = dp[i][i + 1] = 0.

Предположим, что при убирании чисел внутри отрезка [ai, …, aj] последним будет убрано ak (i < k < j). При этом оно в общую сумму принесет слагаемое ai ak aj. Но для того чтобы ak на последнем шаге выбора карты было соседним с ai и aj, необходимо перед этим убрать все карты внутри отрезков [ai, …, ak] и [ak, …, aj]. То есть

f(i, j) =

 

Реализация алгоритма

 

#include <string.h>

#include <stdio.h>

#define MAX 110

#define INF 0x3F3F3F3F

 

int dp[MAX][MAX], a[MAX];

int i,j,k,n,g;

 

int min(int i, int j)

{

  return (i < j) ? i : j;

}

 

int f(int i, int j)

{

  if (dp[i][j] == INF)

    for (int k = i + 1; k < j; k++)

      dp[i][j] = min(dp[i][j], f(i,k) + f(k,j) + a[i] * a[k] * a[j]);

  return dp[i][j];

}

 

int main(void)

{

  scanf("%d",&n);

  memset(dp,0x3F,sizeof(dp));

  for(i = 0; i < n; i++)

  {

    scanf("%d",&a[i]);

    dp[i][i] = 0;

    dp[i][i+1] = 0;

  }

 

  printf("%d\n",f(0,n-1));

  return 0;

}